﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;

namespace NExt.Handler.Base.Default
{
    public class DefaultResponseBuilder: IResponseBuilder
    {
        private readonly IReponseStreamBuilder reponseSreamBuilder;
        private readonly IDictionary<string, string> headerParameters;
        private readonly IDictionary<string, string> mimeTypes;

        public DefaultResponseBuilder(IReponseStreamBuilder reponseSreamBuilder)
            : this(new Dictionary<string, string>(), reponseSreamBuilder)
        {
        }

        public DefaultResponseBuilder(IDictionary<string, string> headerParameters, IReponseStreamBuilder reponseSreamBuilder)
        {
            this.mimeTypes = BuildMimeTypes();
            this.reponseSreamBuilder = reponseSreamBuilder;
            this.headerParameters = headerParameters;
        }

        protected virtual IDictionary<string, string> BuildMimeTypes()
        {
            IDictionary<string, string> mimeTypes = new Dictionary<string, string>();
            mimeTypes.Add(".css", "text/css");
            mimeTypes.Add(".js", "application/x-javascript");
            mimeTypes.Add(".jpeg", "image/jpeg");
            mimeTypes.Add(".jpg", "image/jpeg");
            mimeTypes.Add(".gif", "image/gif");
            mimeTypes.Add(".png", "image/png");

            return mimeTypes;
        }

        public void Build(HttpContext context)
        {
            WriteContentTypeHeader(context);
            foreach (KeyValuePair<string, string> header in headerParameters)
            {
                context.Response.AddHeader(header.Key, header.Value);
            }
            context.Response.ContentEncoding = System.Text.Encoding.UTF8;

            Stream stream = reponseSreamBuilder.Build(context);
            CopyStream(stream, context.Response.OutputStream);
        }

        private void WriteContentTypeHeader(HttpContext context)
        {
            if (headerParameters.ContainsKey("Content-Type"))
                return;

            Uri uri = context.Request.Url;
            string mimeType = GetMimeType(uri);
            context.Response.AddHeader("Content-Type", mimeType);
        }

        private string GetMimeType(Uri uri)
        {
            string resourceName = uri.Segments[uri.Segments.Length - 1];
            string extension = Path.GetExtension(resourceName);
            if (!mimeTypes.ContainsKey(extension))
                return string.Empty;

            return mimeTypes[extension];
        }

        private void CopyStream(Stream fromStream, Stream toStream)
        {
            fromStream.Seek(0, SeekOrigin.Begin);
            byte[] buffer = new byte[0x400];
            int count = 1;
            while (count > 0)
            {
                count = fromStream.Read(buffer, 0, 0x400);
                toStream.Write(buffer, 0, count);
            }
            toStream.Flush();
        }
    }
}
